#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

#define TASK_NUM 5
typedef void(*task_t)();

///////////////////////////////////////////////////////////////////////////////// 
void download()
{
    printf("this is a download task is running!\n");
}

void printLog()
{
    printf("this is a write log task is running!\n");
}

void show()
{
    printf("this is a show task is running!\n");
}
///////////////////////////////////////////////////////////////////////////////// 
// 初始化任务表
void InitTasks(task_t tasks[],int num)
{
    int i = 0; 
    for(; i < num ; i++)
    {
        tasks[i] = NULL;
    }
}

// 添加任务
int AddTask(task_t tasks[], int num ,task_t task)
{
    int i = 0; 
    for( ; i < num ; i++)
    {
        if(tasks[i] == NULL)
        {
            tasks[i] = task;
            return 1;
        }
    }
    return 0;
}

// 该函数内部使用了回调式执行任务
// 可以在函数的内部自行增加或移除任务
void executeTask(task_t tasks[] , int num)
{
    int i = 0;
    for(; i < num ; i++)
    {
        if(tasks[i])    tasks[i]();
    }
}

// 为子进程调用设计的函数
void Worker()
{
    int cnt = 3;
    while(cnt)
    {
        printf("I am child process , pid: %d , ppid : %d , cnt : %d\n" ,getpid(),getppid(),cnt--);
        sleep(1);
    }
}


int main()
{
    // 定义一个任务表
    task_t tasks[TASK_NUM];

    // 初始化并添加任务到任务表中
    InitTasks(tasks,TASK_NUM);
    AddTask(tasks,TASK_NUM,download);
    AddTask(tasks,TASK_NUM,printLog);
    AddTask(tasks,TASK_NUM,show);

    pid_t id = fork();
    
    if(id == 0)
    {
        // child
        Worker();

        exit(0);
    }
    else 
    {
        // 非阻塞轮询等待
        while(1)
        {
            // 获取子进程退出信息
            int status = 0;
            pid_t rid = waitpid(id,&status,WNOHANG);

            if(rid > 0) // 等待成功，且子进程退出
            {
                printf("child quit success , exit code : %d , exit sig : %d\n",status>>8,status&0x7F);
                break;
            }
            else if(rid == 0) // 等待成功，但子进程未退出，重复等待
            {
                printf("------------------------------------------------------\n");
                printf("child is alive , wait again , father do other thing...\n");
                executeTask(tasks,TASK_NUM);
                printf("------------------------------------------------------\n");
            }
            else // rid < 0 ，等待失败,通常是id出错导致的 
            {
                printf("wait failed!\n");
                break;
            }
            
            sleep(1);
        }
    }

    return 0;
}



//#include <stdio.h>
//#include <sys/types.h>
//#include <sys/wait.h>
//#include <unistd.h>
//#include <stdlib.h>
//
//void Worker()
//{
//    int cnt = 3;
//    while(cnt)
//    {
//        printf("I am child process , pid: %d , ppid : %d , cnt : %d\n" ,getpid(),getppid(),cnt--);
//        sleep(1);
//    }
//}
//
//
//int main()
//{
//    pid_t id = fork();
//    
//    if(id == 0)
//    {
//        // child
//        Worker();
//
//        exit(0);
//    }
//    else 
//    {
//        // 获取子进程退出信息
//        int status = 0;
//        pid_t rid = waitpid(id,&status,WNOHANG);
//
//        if(rid > 0) // 等待成功，且子进程退出
//        {
//            printf("child quit success , exit code : %d , exit sig : %d\n",status>>8,status&0x7F);
//        }
//        else if(rid == 0) // 等待成功，但子进程未退出，重复等待
//        {
//            printf("child is alive , wait again , father do other thing...\n");
//        }
//        else // rid < 0 ，等待失败,通常是id出错导致的 
//        {
//            printf("wait failed!\n");
//        }
//        
//        sleep(1);
//    }
//
//    return 0;
//}


//#include <stdio.h>
//#include <sys/types.h>
//#include <sys/wait.h>
//#include <unistd.h>
//#include <stdlib.h>
//
//void Worker(int number)
//{
//    int cnt = 3;
//    while(cnt)
//    {
//        printf("I am child process , pid: %d , ppid : %d , cnt : %d , number : %d\n" ,getpid(),getppid(),cnt--,number);
//        sleep(1);
//    }
//}
//
//#define n 6 
//
//int main()
//{
//    for(int i = 0 ; i < n ; i++)
//    {
//        pid_t id = fork();
//        
//        if(id == 0)
//        {
//            // child
//            Worker(i);
//
//            exit(i);
//        }
//
//    }
//
//    for(int i = 0 ; i < n ; i++)
//    {
//        int status = 0;
//        pid_t rid = waitpid(-1,&status,0);
//        if(rid > 0)
//        {
//            printf("wait child %d success , exit code : %d\n",rid,WEXITSTATUS(status));
//        }
//    }
//    return 0;
//}


//#include <stdio.h>
//#include <sys/types.h>
//#include <sys/wait.h>
//#include <unistd.h>
//#include <stdlib.h>
//
//void Worker()
//{
//    int cnt = 3;
//    while(cnt)
//    {
//        printf("I am child process , pid: %d , ppid : %d , cnt : %d\n" ,getpid(),getppid(),cnt--);
//        sleep(1);
//    }
//}
//
//int main()
//{
//    pid_t id = fork();
//
//    if(id == 0)
//    {
//        // 子进程
//        Worker();
//
//        exit(10);
//    }
//    else 
//    {
//        // 父进程
//        printf("Wait before\n");
//        
//        int status = 0;
//
//        pid_t rid = waitpid(-1,&status,0);
//
//        printf("Wait after\n");
//
//        if(rid == id)
//        {
//            if(WIFEXITED(status))
//                printf("child process normal quit , pid : %d , status : %d , exit code : %d\n",getpid(),status,WEXITSTATUS(status));
//            else 
//                printf("child process quit except!\n");
//        }
//
//        // if(rid == id)
//        //    printf("Wait success , pid : %d , status : %d , exit sig : %d , exit code : %d\n",getpid(),status , status>>8 , status&(0xFF));
//        
//        sleep(3);
//    }
//    return 0;
//}
//


//#include <stdio.h>
//#include <sys/wait.h>
//#include <unistd.h>
//#include <stdlib.h>
//
//void Worker()
//{
//    int cnt = 3;
//    while(cnt)
//    {
//        printf("I am child process , pid: %d , ppid : %d , cnt : %d\n" ,getpid(),getppid(),cnt--);
//        sleep(1);
//    }
//}
//
//int main()
//{
//    pid_t id = fork();
//
//    if(id == 0)
//    {
//        // 子进程
//        Worker();
//
//        exit(0);
//    }
//    else 
//    {
//        // 父进程
//        printf("Wait before\n");
//
//        pid_t rid = wait(NULL);
//
//        printf("Wait after\n");
//
//        if(rid == id)
//            printf("Wait success , pid : %d\n",getpid());
//
//        sleep(3);
//    }
//    return 0;
//}


//#include <stdio.h>
//#include <sys/types.h>
//#include <sys/wait.h>
//#include <unistd.h>
//#include <stdlib.h>
//
//void Worker()
//{
//    int cnt = 3;
//    while(cnt)
//    {
//        printf("I am child process , pid: %d , ppid : %d , cnt : %d\n" ,getpid(),getppid(),cnt--);
//        sleep(1);
//    }
//}
//
//int main()
//{
//    pid_t id = fork();
//
//    if(id == 0)
//    {
//        // 子进程
//        Worker();
//
//        exit(0);
//    }
//    else 
//    {
//        // 父进程
//        sleep(5);  // 用来观察子进程的僵尸状态
//
//        pid_t rid = wait(NULL);
//        if(rid == id)
//            printf("Wait success , pid : %d\n",getpid());
//
//        sleep(3);
//    }
//    return 0;
//}
